Manticore supports basic transactions when performing deleting and insertion into real-time and percolate indexes. That is: each change to an index is first saved into an internal changeset, and then is actually committed to the index. By default each command is wrapped into an individual automatic transaction, making it transparent: you just 'insert' something, and can see the inserted result after it completes, having no care about transactions. However that behaviour can be explicitly managed by starting and committing transactions manually.
Transactions are supported for the following commands:
Transactions are not supported for:
- UPDATE (which is different from the REPLACE in that it does in-place attribute update).
- ALTER - for updating index schema
- TRUNCATE - for emptying a real-time index
- ATTACH - for attaching a plain index to a real-time index
- CREATE - for creating an index
SET AUTOCOMMIT = {0 | 1}
SET AUTOCOMMIT
controls the autocommit mode in the active session. AUTOCOMMIT
is set to 1 by default. With default you have not to care about transactions, since every statement that performs any changes on any index is implicitly wrapped into separate transaction. Setting it to 0 allows you to manage transactions manually. I.e., they will not be visible until you explicitly commit them.
Transactions are limited to a single RT or percolate index, and also limited in size. They are atomic, consistent, overly isolated, and durable. Overly isolated means that the changes are not only invisible to the concurrent transactions but even to the current session itself.
START TRANSACTION | BEGIN
COMMIT
ROLLBACK
BEGIN
statement (or its START TRANSACTION
alias) forcibly commits pending transaction, if any, and begins a new one.
COMMIT
statement commits the current transaction, making all its changes permanent.
ROLLBACK
statement rolls back the current transaction, canceling all its changes.
insert into indexrt (id, content, title, channel_id, published) values (1, 'aa', 'blabla', 1, 10);
Query OK, 1 rows affected (0.00 sec)
select * from indexrt where id=1;
+------+------------+-----------+--------+
| id | channel_id | published | title |
+------+------------+-----------+--------+
| 1 | 1 | 10 | blabla |
+------+------------+-----------+--------+
1 row in set (0.00 sec)
Inserted value immediately visible by following 'select' statement.
set autocommit=0;
Query OK, 0 rows affected (0.00 sec)
insert into indexrt (id, content, title, channel_id, published) values (3, 'aa', 'bb', 1, 1);
Query OK, 1 row affected (0.00 sec)
insert into indexrt (id, content, title, channel_id, published) values (4, 'aa', 'bb', 1, 1);
Query OK, 1 row affected (0.00 sec)
select * from indexrt where id=3;
Empty set (0.01 sec)
select * from indexrt where id=4;
Empty set (0.00 sec)
Here changes is NOT automatically committed. So, insertion is not visible even in the same session, since they're not committed. Also, despite absent BEGIN
statement, transaction is implicitly started.
So, let's finally commit it:
commit;
Query OK, 0 rows affected (0.00 sec)
select * from indexrt where id=4;
+------+------------+-----------+-------+
| id | channel_id | published | title |
+------+------------+-----------+-------+
| 4 | 1 | 1 | bb |
+------+------------+-----------+-------+
1 row in set (0.00 sec)
select * from indexrt where id=3;
+------+------------+-----------+-------+
| id | channel_id | published | title |
+------+------------+-----------+-------+
| 3 | 1 | 1 | bb |
+------+------------+-----------+-------+
1 row in set (0.00 sec)
Now it is finished and visible.
Using BEGIN
and COMMIT
you can define bounds of transaction explicitly, so no need to care about autocommit in this case.
begin;
Query OK, 0 rows affected (0.00 sec)
insert into indexrt (id, content, title, channel_id, published) values (2, 'aa', 'bb', 1, 1);
Query OK, 1 row affected (0.00 sec)
select * from indexrt where id=2;
Empty set (0.01 sec)
commit;
Query OK, 0 rows affected (0.01 sec)
select * from indexrt where id=2;
+------+------------+-----------+-------+
| id | channel_id | published | title |
+------+------------+-----------+-------+
| 2 | 1 | 1 | bb |
+------+------------+-----------+-------+
1 row in set (0.01 sec)
SET TRANSACTION ISOLATION LEVEL { READ UNCOMMITTED
| READ COMMITTED
| REPEATABLE READ
| SERIALIZABLE }
SET TRANSACTION
statement does nothing. It was implemented to maintain compatibility with 3rd party MySQL client libraries, connectors, and frameworks that may need to run this statement when connecting. They just goes across syntax parser and then returns 'ok'. Nothing usable for your own programs, just a stubs to make third-party clients happy.
mysql> SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
Query OK, 0 rows affected (0.00 sec)
✔ ️Searching
Full-text matching
The MATCH
clause allows to perform full-text searches in text fields. The query string at input is tokenized using same settings applied to the text during indexing. In addition to tokenization of input text, the query string supports a number of full-text operators that allow enforcing different rules on how keywords should provide a valid match.
The full-text match clauses can be combined with attribute filters as an AND boolean. OR relation between full-text matches and attribute filters are not supported.
The match query is always executed first in the filtering process, followed by the attribute filters. The attribute filters are applied on the result set of the match query. A query without a match clause is called a fullscan.
There must be at most one MATCH()
in the SELECT
clause.
Using the full-text query syntax matching is performed over all indexed text fields of a document, unless the expression requires to be match within a field (like phrase search) or limited by field operators.
SELECT * FROM index WHERE MATCH('cats|birds');
SELECT statement uses MATCH clause for performing full-text searches. It accepts an input string in which all full-text operators are available.
- SQL
SELECT * FROM myindex WHERE MATCH('"find me fast"/2');
+------+------+----------------+
| id | gid | title |
+------+------+----------------+
| 1 | 11 | first find me |
| 2 | 12 | second find me |
+------+------+----------------+
2 rows in set (0.00 sec)
Full-text matching is available in the /search
endpoint and in HTTP-based clients. The following clauses can be used for performing full-text matches:
"match" is a simple query that matches the specified keywords in the specified fields
"query":
{
"match": { "field": "keyword" }
}
You can specify a list of fields:
"match":
{
"field1,field2": "keyword"
}
Or you can use _all
or *
to search all fields.
You can search all fields except one using "!field":
"match":
{
"!field1": "keyword"
}
By default keywords are combined using the OR operator. However, you can change that behaviour using the "operator" clause:
"query":
{
"match":
{
"content,title":
{
"query":"keyword",
"operator":"or"
}
}
}
"operator" can be set to "or" or "and".
"match_phrase" is a query that matches the entire phrase. It is similar to a phrase operator in SQL. Here's an example:
"query":
{
"match_phrase": { "_all" : "had grown quite" }
}
"query_string" accepts an input string as a full-text query in MATCH()
syntax
"query":
{
"query_string": "Church NOTNEAR/3 street"
}
All full-text match clauses can be combined with must, must_not and should operators of an HTTP bool
query.
- match
- match_phrase
- query_string
- PHP
- Python
- javascript
- Java
POST /search
-d
'{ "index" : "myindex",
"query":
{
"match":
{
"*" : "find me"
}
}
}'
POST /search
-d
'{ "index" : "myindex",
"query":
{
"match_phrase":
{
"*" : "find me"
}
}
}'
POST /search
-d
'{ "index" : "myindex",
"query":
{
"query_string": "@title \"find me fast \"/2"
}
}'
$search = new Search(new Client());
$result = $search->('@title find me fast');
foreach($result as $doc)
{
echo 'Document: '.$doc->getId();
foreach($doc->getData() as $field=>$value)
{
echo $field.': '.$value;
}
}
searchApi.search({"index":"myindex","query":{"query_string":"@title \"find me fast \"/2"}})
res = await searchApi.search({"index":"myindex","query":{"query_string":"@title \"find me fast \"/2"}});
query = new HashMap<String,Object>();
query.put("query_string","@title \"find me fast \"/2");
searchRequest = new SearchRequest();
searchRequest.setIndex("forum");
searchRequest.setQuery(query);
searchResponse = searchApi.search(searchRequest);
{
"took":10,
"timed_out": false,
"hits":
{
"total": 2,
"hits":
[
{
"_id": "1",
"_score": 1,
"_source": {"title":"first find me fast", "gid": 11 }
},
{
"_id": "2",
"_score": 1,
"_source": { "title":"second find me fast", "gid": 12 }
}
]
}
}
{
"took":10,
"timed_out": false,
"hits":
{
"total": 2,
"hits":
[
{
"_id": "1",
"_score": 1,
"_source": {"title":"first find me fast", "gid": 11 }
},
{
"_id": "2",
"_score": 1,
"_source": { "title":"second find me fast", "gid": 12 }
}
]
}
}
{
"took":10,
"timed_out": false,
"hits":
{
"total": 2,
"hits":
[
{
"_id": "1",
"_score": 1,
"_source": {"title":"first find me fast", "gid": 11 }
},
{
"_id": "2",
"_score": 1,
"_source": { "title":"second find me fast", "gid": 12 }
}
]
}
}
Document: 1
title: first find me fast
gid: 11
Document: 2
title: second find me fast
gid: 12
{'hits': {'hits': [{u'_id': u'1',
u'_score': 1,
u'_source': {u'title': u'first find me fast', u'gid':11}},
{u'_id': u'2',
u'_score': 1,
u'_source': {u'title': u'second find me fast', u'gid':12}}],
'total': 2},
'profile': None,
'timed_out': False,
'took': 0}
{"hits": {"hits": [{"_id": "1",
"_score": 1,
"_source": {"title": "first find me fast", "gid":11}},
{"_id": "2",
"_score": 1,
"_source": {"title": "second find me fast", "gid":12}}],
"total": 2},
"profile": None,
"timed_out": False,
"took": 0}
class SearchResponse {
took: 0
timedOut: false
hits: class SearchResponseHits {
total: 2
hits: [{_id=1, _score=1, _source={title=first find me fast, gid=11}}, {_id=2, _score=1, _source={title=first find me fast, gid=12}}]
aggregations: null
}
profile: null
}